//
//  DTodayViewController.swift
//  Drop
//
//  Created by hushaohua on 2017/11/13.
//  Copyright © 2017年 init. All rights reserved.
//

import UIKit
import CoreData
import UserNotifications

class DTodayViewController: UIViewController, UITableViewDelegate, UITableViewDataSource, NSFetchedResultsControllerDelegate {
    
    override init(nibName nibNameOrNil: String?, bundle nibBundleOrNil: Bundle?) {
        super.init(nibName: nibNameOrNil, bundle: nibBundleOrNil);
        self.title = "Today";
    }
    
    required init?(coder aDecoder: NSCoder) {
        fatalError("init(coder:) has not been implemented")
    }
    
    override func viewDidLoad() {
        super.viewDidLoad()

        // Do any additional setup after loading the view.
        self.view.backgroundColor = UIColor.white;
        self.configTableView();
        self.configNavigationItem();
        self.configDropsController();
        self.requestNewest();
        self.configDroppingView();
    }
    
    override func viewDidAppear(_ animated: Bool) {
        super.viewDidAppear(animated);
        self.droppingView.startBright();
    }
    
    override func viewDidDisappear(_ animated: Bool) {
        super.viewDidDisappear(animated);
    }
    
    override func viewWillDisappear(_ animated: Bool) {
        super.viewWillDisappear(animated);
    }
    
    func configTableView() -> Void{
        self.tableView.tableFooterView = UIView();
        self.tableView.rowHeight = 64;
        self.tableView.separatorStyle = .none;
        self.tableView.register(DDropLineTableViewCell.self, forCellReuseIdentifier: DDropLineTableViewCell.normalReuseId);
        self.view.addSubview(self.tableView);
    }
    
    lazy var tableView:UITableView = {
        var tableView:UITableView = UITableView(frame: self.view.bounds, style: .plain);
        tableView.delegate = self;
        tableView.dataSource = self;
        return tableView;
    }();
    
    //MARK: - doing
    func configDroppingView() -> Void {
        let manager = DDroppingManager.sharedManager();
        manager.getDoingDrop();
        if (manager.doingDrop != nil){
            self.tableView.tableHeaderView = self.droppingView;
            let dateFormat:DateFormatter = DateFormatter();
            if Calendar.current.isDateInToday(manager.doingDrop!.begin! as Date){
                dateFormat.dateFormat = "HH:mm";
            }else{
                dateFormat.dateFormat = "MM-dd HH:mm";
            }
            let dateString = dateFormat.string(from: manager.doingDrop!.begin! as Date);
            self.droppingView.beginDateLabel.text = "\(dateString)";
        }else{
            manager.start();
        }
    }
    
    lazy var droppingView:DTodayHeaderView = {
        var view:DTodayHeaderView = DTodayHeaderView(frame: CGRect(origin:.zero, size:CGSize(width:self.view.bounds.width, height:64)));
        return view;
    }();
    
    //MARK:-
    func configDropsController() -> Void {
        self.addDropsNotifications();
        self.dropsController.delegate = self;
    }
    func addDropsNotifications() -> Void {
        let center = NotificationCenter.default;
        center.addObserver(self, selector: #selector(didReceiveNewDropping), name: Notification.Name(DDroppingManager.HDroppingDidNewNotification), object: nil);
        center.addObserver(self, selector: #selector(currentDayDidChanged(_:)), name: Notification.Name(DDateManager.HTodayDidChangedNotification), object: nil);
    }
    
    @objc func didReceiveNewDropping() -> Void{
        self.configDroppingView();
    }
    
    @objc func currentDayDidChanged(_ notification:Notification) -> Void{
        self.requestNewest();
    }
    
    func requestNewest() -> Void{
        do{
            self.dropsController.fetchRequest.predicate = self.todayRequestPredicate();
            try self.dropsController.performFetch()
        }catch{
            let nserror = error as NSError
            fatalError("tags controller fetch error \(nserror), \(nserror.userInfo)")
        }
    }
    
    //MARK:- NSFetchedResultsController
    lazy var dropsController:NSFetchedResultsController<Drop> = {
        let request:NSFetchRequest = Drop.defaultFetchRequest();
        let sortDes:NSSortDescriptor = Drop.defaultSort();
        request.sortDescriptors = [sortDes];
        request.fetchLimit = 30;
        request.predicate = self.todayRequestPredicate();
        var controller:NSFetchedResultsController<Drop> = NSFetchedResultsController(fetchRequest: request, managedObjectContext: HStoreManager.defaultManger().context, sectionNameKeyPath: nil, cacheName: nil);
        return controller;
    }();
    
    func todayRequestPredicate() -> NSPredicate{
        let today:Date = Date();
        let beginDate = Calendar.current.startOfDay(for: today);
        let endDate = Calendar.current.date(byAdding: .day, value: 1, to: beginDate)!;
        let predicate:NSPredicate = NSPredicate(format: "(end != nil AND end >= %@ AND begin <= %@)", beginDate as NSDate, endDate as NSDate);//   在今天结束的
        return predicate;
    }
    
    func controllerWillChangeContent(_ controller: NSFetchedResultsController<NSFetchRequestResult>) {
        self.tableView.beginUpdates();
    }
    
    func controllerDidChangeContent(_ controller: NSFetchedResultsController<NSFetchRequestResult>) {
        self.tableView.endUpdates();
    }
    
    func controller(_ controller: NSFetchedResultsController<NSFetchRequestResult>, didChange anObject: Any, at indexPath: IndexPath?, for type: NSFetchedResultsChangeType, newIndexPath: IndexPath?) {
        switch type {
        case .insert:
            self.tableView.insertRows(at: [newIndexPath!], with: .automatic);
        case .update:
            self.tableView.reloadRows(at: [indexPath!], with: .automatic);
        case .delete:
            self.tableView.deleteRows(at: [indexPath!], with: .automatic);
        default:
            break;
        }
    }
    
    func tableView(_ tableView: UITableView, heightForRowAt indexPath: IndexPath) -> CGFloat {
        return 64;
    }
    //MARK:- tableView
    func numberOfSections(in tableView: UITableView) -> Int {
        return 1;
    }
    
    func tableView(_ tableView: UITableView, numberOfRowsInSection section: Int) -> Int {
        if (self.dropsController.fetchedObjects != nil){
            return self.dropsController.fetchedObjects!.count;
        }else{
            return 0;
        }
    }
    
    func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell {
        let cell:DDropLineTableViewCell = tableView.dequeueReusableCell(withIdentifier: DDropLineTableViewCell.normalReuseId, for: indexPath) as! DDropLineTableViewCell;
        cell.marginLeftOffset = 0;
        cell.selectionStyle = .none;
        let drop:Drop = self.dropsController.object(at: indexPath) as Drop;
        let dayFormatter:DateFormatter = DateFormatter();
        dayFormatter.dateFormat = "HH:mm";
        let beginString:String? = dayFormatter.string(from: drop.begin! as Date);
        cell.beginDateLabel?.text = beginString;
        
        var timeString:String? = nil;
        let interval:Int = Int(drop.end!.timeIntervalSince(drop.begin! as Date));
        if (interval < 60){
            timeString = "1'";
        }else if (interval < 3600){
            timeString = "\(interval / 60)'";
        }else{
            timeString = "\(interval / 3600):\((interval % 3600)/60)'";
        }
        if (drop.hideNote || drop.note == nil){
            cell.titleLabel?.text = "\(drop.tag!.name)(\(timeString!))";
        }else{
            cell.titleLabel?.text = "\(drop.tag!.name)(\(timeString!))\n\(drop.note!)";
        }
        
        weak var weakSelf = self;
        cell.customRevokeClosure = {(aCell) in
            weakSelf?.revokeAction(aCell);
        };
        cell.customModifyTagClosure = {(aCell) in
            weakSelf?.modifyTagAction(aCell);
        };
        cell.updateNoteClosure = {(aCell) in
            weakSelf?.updateNoteAction(aCell);
        };
        cell.tapTitleClosure = {(aCell) in
            weakSelf?.tapTitleAction(aCell);
        };
        cell.shouldRevoke = { (aCell) in
            return weakSelf != nil ? weakSelf!.shouldRevokeFor(aCell) : false;
        };
        cell.shouldModifyTag = {(aCell) in
            return weakSelf != nil ? weakSelf!.shouldModifyTagFor(aCell) : false;
        };
        cell.shouldNote = {(aCell) in
            return weakSelf != nil ? weakSelf!.shouldNoteFor(aCell) : false;
        };
        
        return cell;
    }
    func shouldRevokeFor(_ cell:UITableViewCell) -> Bool {
        let indexPath:IndexPath? = self.tableView.indexPath(for: cell);
        if (indexPath != nil){
            let drop:Drop = self.dropsController.object(at: indexPath!) as Drop;
            if (drop.tag != nil && drop.end != nil){
                let interval = Date().timeIntervalSince(drop.end! as Date);
                if (interval < 120 && indexPath!.section == 0 && indexPath!.row == 0){
                    return true;
                }
            }
        }
        return false;
    }
    func shouldModifyTagFor(_ cell:UITableViewCell) -> Bool {
        let indexPath:IndexPath? = self.tableView.indexPath(for: cell);
        if (indexPath != nil){
            let drop:Drop = self.dropsController.object(at: indexPath!) as Drop;
            if (drop.tag != nil && drop.end != nil){
                let interval = Date().timeIntervalSince(drop.end! as Date);
                if (interval < 120){
                    return true;
                }
            }
        }
        return false;
    }
    func shouldNoteFor(_ cell:UITableViewCell) -> Bool {
        return true;
    }
    func revokeAction(_ cell:UITableViewCell) -> Void {
        let indexPath:IndexPath? = self.tableView.indexPath(for: cell);
        if (indexPath != nil){
            let drop:Drop = self.dropsController.object(at: indexPath!) as Drop;
            DDroppingManager.sharedManager().revokeLatestDrop(drop);
        }
    }
    
    func modifyTagAction(_ cell:UITableViewCell) -> Void {
        let indexPath:IndexPath? = self.tableView.indexPath(for: cell);
        if (indexPath != nil){
            let drop:Drop = self.dropsController.object(at: indexPath!) as Drop;
            DDroppingManager.sharedManager().gotoDropInto(drop);
        }
    }
    func updateNoteAction(_ cell:UITableViewCell) -> Void {
        let indexPath:IndexPath? = self.tableView.indexPath(for: cell);
        if (indexPath != nil){
            let window = UIApplication.shared.keyWindow!;
            let dropCell:DDropLineTableViewCell = cell as! DDropLineTableViewCell;
            let tagFrame = dropCell.titleLabel!.convert(dropCell.titleLabel!.bounds, to: window);
            let beginFrame = dropCell.beginDateLabel!.convert(dropCell.beginDateLabel!.bounds, to: window);
            var endFrame = beginFrame;
            let cellY = dropCell.convert(dropCell.bounds.origin, to: window).y;
            endFrame.origin.y = cellY - beginFrame.size.height;
            
            let drop:Drop = self.dropsController.object(at: indexPath!) as Drop;
            let controller = DDropNoteViewController();
            controller.sourceBeginDateFrame = beginFrame;
            controller.sourceEndDateFrame = endFrame;
            controller.sourceTagFrame = tagFrame;
            controller.modalPresentationStyle = .overCurrentContext;
            controller.drop = drop;
            weak var weakSelf = self;
            controller.didUpdateDropNote = {
                weakSelf?.tableView.reloadRows(at: [indexPath!], with: .automatic);
            };
            self.present(controller, animated: false, completion: nil);
        }
    }
    func tapTitleAction(_ cell:UITableViewCell) {
        let indexPath:IndexPath? = self.tableView.indexPath(for: cell);
        if (indexPath != nil){
            let drop:Drop = self.dropsController.object(at: indexPath!) as Drop;
            if (drop.note != nil){
                drop.hideNote = !drop.hideNote;
                self.tableView.reloadRows(at: [indexPath!], with: .automatic);
            }else{
                drop.hideNote = true;
            }
        }
    }
    func tableView(_ tableView: UITableView, shouldShowMenuForRowAt indexPath: IndexPath) -> Bool {
        return true;
    }
    
    func tableView(_ tableView: UITableView, canPerformAction action: Selector, forRowAt indexPath: IndexPath, withSender sender: Any?) -> Bool {
        return true;
    }
    
    func tableView(_ tableView: UITableView, performAction action: Selector, forRowAt indexPath: IndexPath, withSender sender: Any?) {
        
    }
    
    //MARK: - navigation
    func configNavigationItem() -> Void {
        let right = UIBarButtonItem(title: "Test", style: .done, target: self, action: #selector(gotoTest));
        self.navigationItem.rightBarButtonItem = right;
    }
    
    @objc func gotoTest() {
        let controller:CTestViewController = CTestViewController()
        controller.hidesBottomBarWhenPushed = true;
        self.navigationController?.pushViewController(controller, animated: true);
    }
    
    override func didReceiveMemoryWarning() {
        super.didReceiveMemoryWarning()
        // Dispose of any resources that can be recreated.
    }
}
